package com.punai.dataanalysis.cblib.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.multi.ListValueMap;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.punai.common.bos.HeaderBo;
import com.punai.common.constant.DictConstants;
import com.punai.common.core.domain.TreeBo;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.core.text.Convert;
import com.punai.common.utils.*;
import com.punai.dataanalysis.cblib.bo.*;
import com.punai.dataanalysis.cblib.constants.CbLibConstants;
import com.punai.dataanalysis.cblib.mapper.FeePriceMapper;
import com.punai.dataanalysis.cblib.service.FeePriceLibService;
import com.punai.dataanalysis.cblib.vo.FeeChapterTreeVo;
import com.punai.dataanalysis.cblib.vo.FeeListVo;
import com.punai.dataanalysis.other.mapper.OtherModuleMapper;
import com.punai.externalccb.domain.EcoCbfeeitem;
import com.punai.externalccb.mapper.EcoCbfeeitemMapper;
import com.punai.externalccb.mysqlbo.EcoCbfeeitemPriceBo;
import com.punai.standard.domain.*;
import com.punai.standard.mapper.*;
import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FeePriceLibServiceImpl implements FeePriceLibService {


    @Autowired
    private StaVersionMapper staVersionMapper;
    @Autowired
    private StaGxChapterMapper staGxChapterMapper;
    @Autowired
    private StaFbChapterMapper staFbChapterMapper;
    @Autowired
    private StaGxFeeMapper staGxFeeMapper;
    @Autowired
    private StaFbFeeMapper staFbFeeMapper;
    @Autowired
    private FeePriceMapper feePriceMapper;
    @Autowired
    private EcoCbfeeitemMapper cbfeeitemMapper;
    @Autowired
    private OtherModuleMapper otherModuleMapper;

    private static final String GX_ROOT_ID = "GX_ROOT_ID";
    private static final String CB_ROOT_ID = "CB_ROOT_ID";

    @Override
    public List<TreeBo> selectTreeData(FeeChapterTreeVo vo) {

        // getLastPublishGxChapterTree(vo);
        List<TreeBo> cxChapterTree = getLastPublishGxChapterTree(vo);
        List<TreeBo> fbChapterTree = getLastPublishFbChapterTree(vo);
        cxChapterTree.addAll(fbChapterTree);
        return cxChapterTree;
    }

    private List<TreeBo> getLastPublishGxChapterTree(FeeChapterTreeVo vo) {
        String versionType = "GX";
        String specialty = vo.getSpecialty();
        // 获取 sta_version type = 'GX' CL JX   专业  specialty = spec_id 表的
        List<StaVersion> staVersions = staVersionMapper.selectList(
                Wrappers.<StaVersion>lambdaQuery()
                        .eq(StaVersion::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(StaVersion::getType, versionType)
                        .eq(StrUtil.isNotBlank(specialty) , StaVersion::getSpecId, specialty)
        );

        List<String> versionIds = new ArrayList<>();
        if (StrUtil.isBlank(specialty)) {
            Map<String, List<StaVersion>> collect = staVersions.stream().collect(Collectors.groupingBy(StaVersion::getSpecId));
            for (List<StaVersion> value : collect.values()) {
                Optional<StaVersion> latestStaVersion = value.stream()
                        .max(Comparator.comparing(StaVersion::getCreateTime));
                if (latestStaVersion.isPresent()) {
                    versionIds.add(latestStaVersion.get().getId());
                }
            }
        } else {
            Optional<StaVersion> latestStaVersion = staVersions.stream()
                    .max(Comparator.comparing(StaVersion::getCreateTime));

            if (!latestStaVersion.isPresent()) {
                return new ArrayList<>();
            }
            StaVersion staVersion = latestStaVersion.get();
            String versionId = staVersion.getId();
            versionIds.add(versionId);
        }

        if (CollUtil.isEmpty(versionIds)) {
            return new ArrayList<>();
        }

        List<StaGxChapter> staGxChapters = staGxChapterMapper.selectList(
                Wrappers.<StaGxChapter>lambdaQuery()
                        .in(StaGxChapter::getVersionId, versionIds)
        );

        StaGxChapter gxTop = new StaGxChapter();
        gxTop.setName("标准工序费用项");
        gxTop.setId("0");
        gxTop.setPid(GX_ROOT_ID);
        // gxTop.setType(GX_ROOT_ID);
        staGxChapters.add(gxTop);
        return TreeBo.convert(staGxChapters,GX_ROOT_ID,GX_ROOT_ID);
    }


    private List<TreeBo> getLastPublishFbChapterTree(FeeChapterTreeVo vo) {
        String versionType = "FB";
        String specialty = vo.getSpecialty();
        // 获取 sta_version type = 'GX' CL JX   专业  specialty = spec_id 表的
        List<StaVersion> staVersions = staVersionMapper.selectList(
                Wrappers.<StaVersion>lambdaQuery()
                        .eq(StaVersion::getCompanyId, SecurityUtils.getCompanyId())
                        .eq(StaVersion::getType, versionType)
                        .eq(StrUtil.isNotBlank(specialty) , StaVersion::getSpecId, specialty)
        );

        List<String> versionIds = new ArrayList<>();
        if (StrUtil.isBlank(specialty)) {
            Map<String, List<StaVersion>> collect = staVersions.stream().collect(Collectors.groupingBy(StaVersion::getSpecId));
            for (List<StaVersion> value : collect.values()) {
                Optional<StaVersion> latestStaVersion = value.stream()
                        .max(Comparator.comparing(StaVersion::getCreateTime));
                latestStaVersion.ifPresent(staVersion -> versionIds.add(staVersion.getId()));
            }
        } else {
            Optional<StaVersion> latestStaVersion = staVersions.stream()
                    .max(Comparator.comparing(StaVersion::getCreateTime));

            if (!latestStaVersion.isPresent()) {
                return new ArrayList<>();
            }
            StaVersion staVersion = latestStaVersion.get();
            String versionId = staVersion.getId();
            versionIds.add(versionId);
        }

        if (CollUtil.isEmpty(versionIds)) {
            return new ArrayList<>();
        }

        List<StaFbChapter> staFbChapters = staFbChapterMapper.selectList(
                Wrappers.<StaFbChapter>lambdaQuery()
                        .in(StaFbChapter::getVersionId, versionIds)
        );

        // staFbChapters
        StaFbChapter fbTop = new StaFbChapter();
        fbTop.setName("企业成本费用项");
        fbTop.setId("0");
        fbTop.setPid(CB_ROOT_ID);
        // fbTop.setType(CB_ROOT_ID);
        staFbChapters.add(fbTop);

        return TreeBo.convert(staFbChapters,CB_ROOT_ID,CB_ROOT_ID);
    }

    @Override
    public TableDataInfo selectFeeList(FeeListVo vo) {

        TableDataInfo result = new TableDataInfo();


        String versionId = vo.getVersionId();
        String chapterId = vo.getChapterId();
        String gxCbType = vo.getGxCbType();
        String specId = vo.getSpecId();
        boolean showExist = vo.isShowExist();

        String addressStr = vo.getAddressStr();
        String deptStr = vo.getDeptStr();

        List<String> deptList = null;
        if (StrUtil.isNotBlank(deptStr)) {
            deptList = StrUtil.split(deptStr,",");
        }
        if (StrUtil.isNotBlank(vo.getStartTime())) {
            vo.setStartTime(vo.getStartTime() + "-01");
        }
        if (StrUtil.isNotBlank(vo.getEndTime())) {
            int totalDaysOfMonth = DateUtil.getTotalDaysOfMonth(DateUtil.getDate(vo.getEndTime()));
            vo.setEndTime(vo.getEndTime() + "-" + totalDaysOfMonth);
        }
        Map<String,Object> params = new HashMap<>();
        params.put("stagetype",vo.getStagetype());
        params.put("address",addressStr);
        params.put("startTime",vo.getStartTime());
        params.put("endTime",vo.getEndTime());
        params.put("code",vo.getCode());
        params.put("name",vo.getName());



        if (StrUtil.equals(GX_ROOT_ID,gxCbType)) {

            List<String> chapterIds = new ArrayList<>();

            if (StrUtil.isNotEmpty(chapterId)) {
                chapterIds.add(chapterId);
                List<StaGxChapter> childByPid = getGxChildByPid(chapterId, versionId);
                if (CollUtil.isNotEmpty(chapterIds)) {
                    chapterIds.addAll(childByPid.stream().map(StaGxChapter::getId).collect(Collectors.toList()));
                }
            }

            // 判定
            long total = 0L;
            List<StaGxFee> staGxFees = new ArrayList<>();
            if (showExist) {
                PageUtils.startPage();
                List<String> codes = feePriceMapper.selectGxListLinkCbfeeItem(versionId, chapterIds, null, deptList, params);
                if (CollUtil.isEmpty(codes)) {
                    return result;
                }
                total = new PageInfo(codes).getTotal();
                staGxFees = staGxFeeMapper.selectList(
                        Wrappers.<StaGxFee>lambdaQuery()
                                .in(StaGxFee::getCode, codes)
                                .eq(StaGxFee::getVersionId, versionId).orderBy(true,true,StaGxFee::getOrderNum)
                );
            } else {
                PageUtils.startPage();
                staGxFees = staGxFeeMapper.selectList(
                        Wrappers.<StaGxFee>lambdaQuery()
                                .in(chapterIds.size() > 0,StaGxFee::getChapterId, chapterIds)
                                .eq(StaGxFee::getVersionId, versionId)
                                .like(StrUtil.isNotBlank(vo.getCode()),StaGxFee::getCode,"%" + vo.getCode() + "%")
                                .like(StrUtil.isNotBlank(vo.getName()),StaGxFee::getName,"%" + vo.getName() + "%")
                                .orderBy(true,true,StaGxFee::getCode)
                                .orderBy(true,true,StaGxFee::getOrderNum)
                );
                total = new PageInfo(staGxFees).getTotal();
            }


            List<String> feeCodes = staGxFees.stream().map(StaGxFee::getCode).collect(Collectors.toList());
            if (CollUtil.isEmpty(feeCodes)) {
                return result;
            }

            params.remove("code");
            params.remove("name");



            List<EcoCbfeeitemPriceBo> cbfeeitems = cbfeeitemMapper.selectByCodesAndOther(feeCodes,null,deptList,params);

            String spliter = "@";
            // 需要分组 按照名称
            Map<String, List<EcoCbfeeitemPriceBo>> codeNameGroup = cbfeeitems.stream().collect(Collectors.groupingBy((item) -> item.getOrgincode() + spliter + item.getName()));


            Set<String> keySet = codeNameGroup.keySet();
            ListValueMap<String,EcoCbfeeitemPriceBo> groupList = new ListValueMap<>();
            for (String key : keySet) {
                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = codeNameGroup.get(key);
                if (CollUtil.isNotEmpty(ecoCbfeeitemPriceBos)) {
                    List<String> split = StrUtil.split(key, spliter);
                    String ocode = split.get(0);
                    EcoCbfeeitemPriceBo priceBo = ecoCbfeeitemPriceBos.get(0);
                    MMAInfo mmaInfo = getMMAInfo(ecoCbfeeitemPriceBos);
                    BigDecimal avgPrice = mmaInfo.getAvgPrice();
                    priceBo.setAvgPrice(avgPrice);
                    priceBo.setFeeAmount(ecoCbfeeitemPriceBos.size());
                    groupList.putValue(ocode,priceBo);
                }
            }

            List<StaGxFeeBo> resultList = new ArrayList<>();
            for (StaGxFee staGxFee : staGxFees) {
                StaGxFeeBo convert = StaGxFeeBo.convert(staGxFee);
                String code = staGxFee.getCode();
                String parseContent = ParseContentUtil.parseContent(convert.getContent());
                convert.setContent(parseContent);
                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = groupList.get(code);
                List<StaGxFeeBo> chidlrenList = StaGxFeeBo.convert(ecoCbfeeitemPriceBos);
                convert.setChildren(chidlrenList);
                resultList.add(convert);
            }
            result.setRows(resultList);
            result.setTotal(total);
            return result;
        } else if (StrUtil.equals(CB_ROOT_ID,gxCbType)){

            List<String> chapterIds = new ArrayList<>();

            if (StrUtil.isNotEmpty(chapterId)) {
                chapterIds.add(chapterId);
                List<StaFbChapter> childByPid = getFbChildByPid(chapterId, versionId);
                if (CollUtil.isNotEmpty(chapterIds)) {
                    chapterIds.addAll(childByPid.stream().map(StaFbChapter::getId).collect(Collectors.toList()));
                }
            }

            // 判定
            long total = 0L;
            List<StaFbFee> staGxFees = new ArrayList<>();
            if (showExist) {
                PageUtils.startPage();
                List<String> codes = feePriceMapper.selectFbListLinkCbfeeItem(versionId, chapterIds, null, deptList, params);
                if (CollUtil.isEmpty(codes)) {
                    return result;
                }
                total = new PageInfo(codes).getTotal();
                staGxFees = staFbFeeMapper.selectList(
                        Wrappers.<StaFbFee>lambdaQuery()
                                .in(StaFbFee::getCode, codes)
                                .eq(StaFbFee::getVersionId, versionId).orderBy(true,true,StaFbFee::getOrderNum)
                );
            } else {
                PageUtils.startPage();
                staGxFees = staFbFeeMapper.selectList(
                        Wrappers.<StaFbFee>lambdaQuery()
                                .in(chapterIds.size() > 0,StaFbFee::getChapterId, chapterIds)
                                .eq(StaFbFee::getVersionId, versionId)
                                .like(StrUtil.isNotBlank(vo.getCode()),StaFbFee::getCode,"%" + vo.getCode() + "%")
                                .like(StrUtil.isNotBlank(vo.getName()),StaFbFee::getName,"%" + vo.getName() + "%")
                                .orderBy(true,true,StaFbFee::getCode)
                                .orderBy(true,true,StaFbFee::getOrderNum)
                );
                total = new PageInfo(staGxFees).getTotal();
            }


            List<String> feeCodes = staGxFees.stream().map(StaFbFee::getCode).collect(Collectors.toList());
            if (CollUtil.isEmpty(feeCodes)) {
                return result;
            }
            params.remove("code");
            params.remove("name");

            List<EcoCbfeeitemPriceBo> cbfeeitems = cbfeeitemMapper.selectByCodesAndOther(feeCodes,null,deptList,params);

            String spliter = "@";
            // 需要分组 按照名称
            Map<String, List<EcoCbfeeitemPriceBo>> codeNameGroup = cbfeeitems.stream().collect(Collectors.groupingBy((item) -> item.getOrgincode() + spliter + item.getName()));


            Set<String> keySet = codeNameGroup.keySet();
            ListValueMap<String,EcoCbfeeitemPriceBo> groupList = new ListValueMap<>();
            for (String key : keySet) {
                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = codeNameGroup.get(key);
                if (CollUtil.isNotEmpty(ecoCbfeeitemPriceBos)) {
                    List<String> split = StrUtil.split(key, spliter);
                    String ocode = split.get(0);
                    EcoCbfeeitemPriceBo priceBo = ecoCbfeeitemPriceBos.get(0);
                    MMAInfo mmaInfo = getMMAInfo(ecoCbfeeitemPriceBos);
                    BigDecimal avgPrice = mmaInfo.getAvgPrice();
                    priceBo.setAvgPrice(avgPrice);
                    priceBo.setFeeAmount(ecoCbfeeitemPriceBos.size());
                    groupList.putValue(ocode,priceBo);
                }
            }

            List<StaFbFeeBo> resultList = new ArrayList<>();
            for (StaFbFee staGxFee : staGxFees) {
                StaFbFeeBo convert = StaFbFeeBo.convert(staGxFee);
                String code = staGxFee.getCode();
                String parseContent = ParseContentUtil.parseContent(convert.getContent());
                convert.setContent(parseContent);
                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = groupList.get(code);
                List<StaFbFeeBo> chidlrenList = StaFbFeeBo.convert(ecoCbfeeitemPriceBos);
                convert.setChildren(chidlrenList);
                resultList.add(convert);
            }
            result.setRows(resultList);
            result.setTotal(total);
            return result;
        }
        // 计算价格
        return result;
    }

    @Override
    public FeepriceAndMMABo getFeeDetailList(FeeListVo vo) {
        String ocode = vo.getOcode();

        String addressStr = vo.getAddressStr();
        String deptStr = vo.getDeptStr();


        List<String> deptList = null;
        if (StrUtil.isNotBlank(deptStr)) {
            deptList = StrUtil.split(deptStr,",");
        }
        if (StrUtil.isNotBlank(vo.getStartTime())) {
            vo.setStartTime(vo.getStartTime() + "-01");
        }
        if (StrUtil.isNotBlank(vo.getEndTime())) {
            int totalDaysOfMonth = DateUtil.getTotalDaysOfMonth(DateUtil.getDate(vo.getEndTime()));
            vo.setEndTime(vo.getEndTime() + "-" + totalDaysOfMonth);
        }
        Map<String,Object> params = new HashMap<>();
        params.put("stagetype",vo.getStagetype());
        params.put("startTime",vo.getStartTime());
        params.put("endTime",vo.getEndTime());
        params.put("name",vo.getName());
        params.put("address",vo.getAddressStr());

        List<String> codes = new ArrayList<>();
        codes.add(ocode);
        PageUtils.startPage();
        List<EcoCbfeeitemPriceBo> cbfeeitems = cbfeeitemMapper.selectByCodesAndOther(codes,null,deptList,params);
        long total = new PageInfo(cbfeeitems).getTotal();
        TableDataInfo tableDataInfo = new TableDataInfo(cbfeeitems, Convert.toInt(total));

        //
        FeepriceAndMMABo resBo = new FeepriceAndMMABo();
        resBo.setTableDataInfo(tableDataInfo);
        // MMA
        MMAInfo mmaInfo = getMMAInfo(cbfeeitems);
        resBo.setMmaInfo(mmaInfo);

        EchartsZXInfo zxInfo = getZxInfo(cbfeeitems);
        resBo.setZxInfo(zxInfo);
        return resBo;
    }

    @Override
    public CompareBo getFeeCompareList(FeeListVo vo) {
        CompareBo compareBo = new CompareBo();

        // 处理参数
        boolean stagetypeOpen = vo.isStagetypeOpen();
        boolean deptOpen = vo.isDeptOpen();

        String stagetype = vo.getStagetypeStr();
        List<String> stagetypeList = StrUtil.split(stagetype, ",");

        String code = vo.getOcode();


        List<String> deptList = null;
        String deptStr = vo.getDeptStr();
        if (deptOpen && StrUtil.isNotBlank(deptStr)) {
            deptList = StrUtil.split(deptStr,",");
        }
        if (StrUtil.isNotBlank(vo.getStartTime())) {
            vo.setStartTime(vo.getStartTime() + "-01");
        }
        if (StrUtil.isNotBlank(vo.getEndTime())) {
            int totalDaysOfMonth = DateUtil.getTotalDaysOfMonth(DateUtil.getDate(vo.getEndTime()));
            vo.setEndTime(vo.getEndTime() + "-" + totalDaysOfMonth);
        }
        Map<String,Object> params = new HashMap<>();
        params.put("startTime",vo.getStartTime());
        params.put("endTime",vo.getEndTime());
        params.put("name",vo.getName());
        params.put("address",vo.getAddressStr());

        List<String> codes = new ArrayList<>();
        codes.add(code);

        List<HeaderBo> headerHzBos = new ArrayList<>();
        List<Map<String, Object>> dataHzList = new ArrayList<>();

        List<HeaderBo> headerBos = new ArrayList<>();
        List<Map<String, Object>> dataList = new ArrayList<>();


        setHzInfo(codes,headerHzBos,dataHzList,stagetypeList,deptList,stagetypeOpen,deptOpen,params);
        setXmInfo(codes,headerBos,dataList,stagetypeList,deptList,stagetypeOpen,deptOpen,params);

        compareBo.setDataHzList(dataHzList);
        compareBo.setHeaderHzBos(headerHzBos);
        compareBo.setDataList(dataList);
        compareBo.setHeaderBos(headerBos);
        return compareBo;
    }

    private void setHzInfo(List<String> codes, List<HeaderBo> headerHzBos, List<Map<String, Object>> dataHzList, List<String> stagetypeList, List<String> deptList,
                           boolean stagetypeOpen, boolean deptOpen, Map<String, Object> params) {
        // 对于汇总来讲  不管勾选与否 都会带上筛选条件
        // 而勾选的意义在于 组建结构的不同    分组  +  前面展示的行
        // 查询
        params.put("stagetypeList",stagetypeList);
        List<EcoCbfeeitemPriceBo> cbfeeHzitems = cbfeeitemMapper.selectByCodesAndOther(codes,null,deptList,params);

        createHzHeader(cbfeeHzitems,headerHzBos);

        // 求整体的
        if (stagetypeOpen && deptOpen) {
            // 先分公司
            Map<String, List<EcoCbfeeitemPriceBo>> deptGroup = cbfeeHzitems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getDeptInfo));
            Set<String> deptKeys = deptGroup.keySet();

            List<Map<String,Object>> maps = otherModuleMapper.selectDeptIdName(deptKeys);

            Map<Long, String> deptIdNameMap = IMapUtil.toMap(maps, "deptId", "deptName");

            for (String deptKey : deptKeys) {

                List<EcoCbfeeitemPriceBo> deptFeeItems = deptGroup.get(deptKey);
                // 分阶段
                Map<String, List<EcoCbfeeitemPriceBo>> stagetypeGroup = deptFeeItems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getStagetype));
                Set<String> keySet = stagetypeGroup.keySet();
                for (String stagetype : keySet) {

                    Map<String, Object> dataItem = new HashMap<>();
                    dataItem.put("fgs",deptIdNameMap.get(Convert.toLong(deptKey)));
                    dataItem.put("stageTypeName",DictUtils.getDictLabel(DictConstants.PROJECT_STAGETYPE,stagetype));

                    List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = stagetypeGroup.get(stagetype);
                    // 前面几行统计固定的
                    MMAInfo allMMAInfo = getMMAInfo(ecoCbfeeitemPriceBos);
                    CbLibConstants.PriceCompareType[] values = CbLibConstants.PriceCompareType.values();
                    for (CbLibConstants.PriceCompareType value : values) {
                        dataItem.put(value.getProp(),value.getValue(allMMAInfo));
                    }

                    ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
                    for (EcoCbfeeitemPriceBo fip : ecoCbfeeitemPriceBos) {
                        Date createTime = fip.getCreateTime();
                        dateGroup.put(DateUtil.dateToyM(createTime),fip);
                    }
                    Set<String> keys = dateGroup.keySet();
                    ArrayList<String> monthList = new ArrayList<>(keys);
                    monthList.sort(String::compareTo);
                    for (String key : monthList) {
                        List<EcoCbfeeitemPriceBo> itemPriceLibraryList = dateGroup.get(key);
                        MMAInfo mmaInfo = getMMAInfo(itemPriceLibraryList);
                        for (CbLibConstants.PriceCompareType compareType : values) {
                            String prop = key + "-" + compareType.getProp();
                            dataItem.put(prop,compareType.getValue(mmaInfo));
                        }
                    }
                    // 保存数据
                    dataHzList.add(dataItem);
                }
            }
        } else if (stagetypeOpen) {
            Map<String, List<EcoCbfeeitemPriceBo>> stagetypeGroup = cbfeeHzitems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getStagetype));
            Set<String> keySet = stagetypeGroup.keySet();
            for (String stagetype : keySet) {

                Map<String, Object> dataItem = new HashMap<>();
                dataItem.put("stageTypeName",DictUtils.getDictLabel(DictConstants.PROJECT_STAGETYPE,stagetype));

                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = stagetypeGroup.get(stagetype);
                // 前面几行统计固定的
                MMAInfo allMMAInfo = getMMAInfo(ecoCbfeeitemPriceBos);
                CbLibConstants.PriceCompareType[] values = CbLibConstants.PriceCompareType.values();
                for (CbLibConstants.PriceCompareType value : values) {
                    dataItem.put(value.getProp(),value.getValue(allMMAInfo));
                }

                ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
                for (EcoCbfeeitemPriceBo fip : ecoCbfeeitemPriceBos) {
                    Date createTime = fip.getCreateTime();
                    dateGroup.put(DateUtil.dateToyM(createTime),fip);
                }
                Set<String> keys = dateGroup.keySet();
                ArrayList<String> monthList = new ArrayList<>(keys);
                monthList.sort(String::compareTo);
                for (String key : monthList) {
                    List<EcoCbfeeitemPriceBo> itemPriceLibraryList = dateGroup.get(key);
                    MMAInfo mmaInfo = getMMAInfo(itemPriceLibraryList);
                    for (CbLibConstants.PriceCompareType compareType : values) {
                        String prop = key + "-" + compareType.getProp();
                        dataItem.put(prop,compareType.getValue(mmaInfo));
                    }
                }
                // 保存数据
                dataHzList.add(dataItem);
            }
        } else if(deptOpen) {
            Map<String, List<EcoCbfeeitemPriceBo>> deptGroup = cbfeeHzitems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getDeptInfo));
            Set<String> deptKeys = deptGroup.keySet();
            for (String deptKey : deptKeys) {
                Map<String, Object> dataItem = new HashMap<>();
                dataItem.put("fgs",deptKey);

                List<EcoCbfeeitemPriceBo> ecoCbfeeitemPriceBos = deptGroup.get(deptKey);
                // 前面几行统计固定的
                MMAInfo allMMAInfo = getMMAInfo(ecoCbfeeitemPriceBos);
                CbLibConstants.PriceCompareType[] values = CbLibConstants.PriceCompareType.values();
                for (CbLibConstants.PriceCompareType value : values) {
                    dataItem.put(value.getProp(),value.getValue(allMMAInfo));
                }

                ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
                for (EcoCbfeeitemPriceBo fip : ecoCbfeeitemPriceBos) {
                    Date createTime = fip.getCreateTime();
                    dateGroup.put(DateUtil.dateToyM(createTime),fip);
                }
                Set<String> keys = dateGroup.keySet();
                ArrayList<String> monthList = new ArrayList<>(keys);
                monthList.sort(String::compareTo);
                for (String key : monthList) {
                    List<EcoCbfeeitemPriceBo> itemPriceLibraryList = dateGroup.get(key);
                    MMAInfo mmaInfo = getMMAInfo(itemPriceLibraryList);
                    for (CbLibConstants.PriceCompareType compareType : values) {
                        String prop = key + "-" + compareType.getProp();
                        dataItem.put(prop,compareType.getValue(mmaInfo));
                    }
                }
                // 保存数据
                dataHzList.add(dataItem);
            }
        } else {
            Map<String, Object> dataItem = new HashMap<>();
            MMAInfo allMMAInfo = getMMAInfo(cbfeeHzitems);
            CbLibConstants.PriceCompareType[] values = CbLibConstants.PriceCompareType.values();
            for (CbLibConstants.PriceCompareType value : values) {
                dataItem.put(value.getProp(),value.getValue(allMMAInfo));
            }

            ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
            for (EcoCbfeeitemPriceBo fip : cbfeeHzitems) {
                Date createTime = fip.getCreateTime();
                dateGroup.put(DateUtil.dateToyM(createTime),fip);
            }

            Set<String> keys = dateGroup.keySet();
            ArrayList<String> monthList = new ArrayList<>(keys);
            monthList.sort(String::compareTo);
            for (String key : monthList) {
                List<EcoCbfeeitemPriceBo> itemPriceLibraryList = dateGroup.get(key);
                MMAInfo mmaInfo = getMMAInfo(itemPriceLibraryList);
                for (CbLibConstants.PriceCompareType compareType : values) {
                    String prop = key + "-" + compareType.getProp();
                    dataItem.put(prop,compareType.getValue(mmaInfo));
                }
            }
            // 保存数据
            dataHzList.add(dataItem);
        }
    }

    private void createHzHeader(List<EcoCbfeeitemPriceBo> cbfeeHzitems, List<HeaderBo> headerHzBos) {
        ListValuedMap<String,EcoCbfeeitemPriceBo> headerGroup = new ArrayListValuedHashMap<>();
        for (EcoCbfeeitemPriceBo fip : cbfeeHzitems) {
            Date createTime = fip.getCreateTime();
            headerGroup.put(DateUtil.dateToyM(createTime),fip);
        }
        Set<String> keys = headerGroup.keySet();
        ArrayList<String> monthList = new ArrayList<>(keys);
        monthList.sort(String::compareTo);

        for (String month : monthList) {
            HeaderBo headerBo = new HeaderBo();
            headerBo.setLabel(month);
            CbLibConstants.PriceCompareType[] values = CbLibConstants.PriceCompareType.values();
            for (CbLibConstants.PriceCompareType value : values) {
                HeaderBo cbo = new HeaderBo();
                cbo.setLabel(value.getLabel());
                cbo.setProp(month + "-" + value.getProp());
                headerBo.getChildren().add(cbo);
            }
            headerHzBos.add(headerBo);
        }
    }

    private void setXmInfo(List<String> codes,List<HeaderBo> headerBos, List<Map<String, Object>> dataList, List<String> stagetypeList, List<String> deptList,
                            boolean stagetypeOpen, boolean deptOpen, Map<String, Object> params) {

        List<CbLibConstants.PriceCompareType> xmdbTab = CbLibConstants.PriceCompareType.getXMDBTab();
        if(stagetypeOpen) {
            params.put("stagetypeList",stagetypeList);
            List<EcoCbfeeitemPriceBo> cbfeeXmitems = cbfeeitemMapper.selectByCodesAndOther(codes,null,deptList,params);

            createXmHeader(cbfeeXmitems,headerBos,stagetypeList);
            Map<String,String> proIdNameMap = new HashMap<>();
            for (EcoCbfeeitemPriceBo cbfeeitem : cbfeeXmitems) {
                proIdNameMap.put(cbfeeitem.getProId(),cbfeeitem.getProName());
            }

            if (deptOpen) {
                Map<String, List<EcoCbfeeitemPriceBo>> deptGroup = cbfeeXmitems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getDeptInfo));
                Set<String> deptKeys = deptGroup.keySet();
                List<Map<String,Object>> maps = otherModuleMapper.selectDeptIdName(deptKeys);

                Map<Long, String> deptIdNameMap = IMapUtil.toMap(maps, "deptId", "deptName");

                for (String deptKey : deptKeys) {
                    List<EcoCbfeeitemPriceBo> deptFeeItems = deptGroup.get(deptKey);
                    Map<String, List<EcoCbfeeitemPriceBo>> proGroup = deptFeeItems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getProId));
                    for (Map.Entry<String, List<EcoCbfeeitemPriceBo>> proEntry : proGroup.entrySet()) {
                        String proId = proEntry.getKey();
                        String proName = proIdNameMap.get(proId);
                        List<EcoCbfeeitemPriceBo> value = proEntry.getValue();

                        // 通过月份分组
                        ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
                        for (EcoCbfeeitemPriceBo fip : value) {
                            Date createTime = fip.getCreateTime();
                            dateGroup.put(DateUtil.dateToyM(createTime),fip);
                        }
                        Set<String> keys = dateGroup.keySet();
                        ArrayList<String> listKeys = new ArrayList<>(keys);
                        listKeys.sort(String::compareTo);

                        Map<String, Object> dataItem = new HashMap<>();

                        dataItem.put("fgs",deptIdNameMap.get(Convert.toLong(deptKey)));
                        dataItem.put("proName",proName);

                        for (String key : listKeys) {
                            // 月份分组
                            List<EcoCbfeeitemPriceBo> monthList = dateGroup.get(key);
                            Map<String, List<EcoCbfeeitemPriceBo>> stagetypeGroup = monthList.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getStagetype));

                            for (Map.Entry<String, List<EcoCbfeeitemPriceBo>> stagetypeEntry : stagetypeGroup.entrySet()) {
                                String stagetype = stagetypeEntry.getKey();
                                List<EcoCbfeeitemPriceBo> stagetypeGroupList = stagetypeEntry.getValue();

                                String propStagetype = key + "-" + stagetype;
                                MMAInfo mmaInfo = getMMAInfo(stagetypeGroupList);
                                dataItem.put(propStagetype,mmaInfo.getMaxPrice());

                                for (CbLibConstants.PriceCompareType compareType : xmdbTab) {
                                    String prop = key + "-" + stagetype + "-" + compareType.getProp();
                                    dataItem.put(prop,compareType.getValue(mmaInfo));
                                }
                            }
                        }
                        dataList.add(dataItem);
                    }
                }
            } else {
                Map<String, List<EcoCbfeeitemPriceBo>> proGroup = cbfeeXmitems.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getProId));
                for (Map.Entry<String, List<EcoCbfeeitemPriceBo>> proEntry : proGroup.entrySet()) {
                    String proId = proEntry.getKey();
                    String proName = proIdNameMap.get(proId);
                    List<EcoCbfeeitemPriceBo> value = proEntry.getValue();

                    // 通过月份分组
                    ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
                    for (EcoCbfeeitemPriceBo fip : value) {
                        Date createTime = fip.getCreateTime();
                        dateGroup.put(DateUtil.dateToyM(createTime),fip);
                    }
                    Set<String> keys = dateGroup.keySet();
                    ArrayList<String> listKeys = new ArrayList<>(keys);
                    listKeys.sort(String::compareTo);

                    Map<String, Object> dataItem = new HashMap<>();

                    dataItem.put("proName",proName);

                    for (String key : listKeys) {
                        // 月份分组
                        List<EcoCbfeeitemPriceBo> monthList = dateGroup.get(key);
                        Map<String, List<EcoCbfeeitemPriceBo>> stagetypeGroup = monthList.stream().collect(Collectors.groupingBy(EcoCbfeeitemPriceBo::getStagetype));

                        for (Map.Entry<String, List<EcoCbfeeitemPriceBo>> stagetypeEntry : stagetypeGroup.entrySet()) {
                            String stagetype = stagetypeEntry.getKey();
                            List<EcoCbfeeitemPriceBo> stagetypeGroupList = stagetypeEntry.getValue();

                            String propStagetype = key + "-" + stagetype;
                            MMAInfo mmaInfo = getMMAInfo(stagetypeGroupList);
                            dataItem.put(propStagetype,mmaInfo.getMaxPrice());

                            for (CbLibConstants.PriceCompareType compareType : xmdbTab) {
                                String prop = key + "-" + stagetype + "-" + compareType.getProp();
                                dataItem.put(prop,compareType.getValue(mmaInfo));
                            }
                        }
                    }
                    dataList.add(dataItem);
                }
            }
        }
    }

    private void createXmHeader(List<EcoCbfeeitemPriceBo> cbfeeXmitems, List<HeaderBo> headerBos, List<String> stagetypeList) {
        ListValuedMap<String,EcoCbfeeitemPriceBo> headerGroup = new ArrayListValuedHashMap<>();
        for (EcoCbfeeitemPriceBo fip : cbfeeXmitems) {
            Date createTime = fip.getCreateTime();
            headerGroup.put(DateUtil.dateToyM(createTime),fip);
        }
        Set<String> keys = headerGroup.keySet();
        ArrayList<String> monthList = new ArrayList<>(keys);
        monthList.sort(String::compareTo);

        for (String month : monthList) {
            HeaderBo headerBo = new HeaderBo();
            headerBo.setLabel(month);
            List<CbLibConstants.PriceCompareType> xmdbTab = CbLibConstants.PriceCompareType.getXMDBTab();
            for (String stageType : stagetypeList) {
                HeaderBo cbo1 = new HeaderBo();
                cbo1.setLabel( DictUtils.getDictLabel(DictConstants.PROJECT_STAGETYPE,stageType));
                cbo1.setProp(month + "-" + stageType);
                headerBo.getChildren().add(cbo1);

                for (CbLibConstants.PriceCompareType value : xmdbTab) {
                    HeaderBo cbo2 = new HeaderBo();
                    cbo2.setLabel(value.getLabel());
                    cbo2.setProp(month + "-" + stageType + "-" + value.getProp());
                    headerBo.getChildren().add(cbo2);
                }
            }

            headerBos.add(headerBo);
        }


    }

    private EchartsZXInfo getZxInfo(List<EcoCbfeeitemPriceBo> cbfeeitems) {
        EchartsZXInfo zxInfo = new EchartsZXInfo();
        ListValuedMap<String,EcoCbfeeitemPriceBo> dateGroup = new ArrayListValuedHashMap<>();
        // 根据月份分组 求平均值
        for (EcoCbfeeitemPriceBo fip : cbfeeitems) {
            Date createTime = fip.getCreateTime();
            dateGroup.put(DateUtil.dateToyM(createTime),fip);
        }
        List<String> names = new ArrayList<>();
        List<BigDecimal> values = new ArrayList<>();
        Set<String> keys = dateGroup.keySet();

        ArrayList<String> listKeys = new ArrayList<>(keys);
        listKeys.sort(String::compareTo);
        for (String key : listKeys) {
            names.add(key);
            List<EcoCbfeeitemPriceBo> itemPriceLibraryList = dateGroup.get(key);
            OptionalDouble average = itemPriceLibraryList.stream().map(EcoCbfeeitemPriceBo::getTargetnotaxprice)
                    .filter(Objects::nonNull).mapToDouble(BigDecimal::doubleValue).average();
            values.add(NumberUtil.getRoundedTY(average.orElse(0)));
        }
        zxInfo.setNames(names);
        zxInfo.setValues(values);
        return zxInfo;
    }


    private List<StaGxChapter> getGxChildByPid(String pid,String versionId) {
        return otherModuleMapper.getChildByPid(pid,versionId);
    }

    private List<StaFbChapter> getFbChildByPid(String pid,String versionId) {
        return otherModuleMapper.getFbChildByPid(pid,versionId);
    }


    private MMAInfo getMMAInfo(List<EcoCbfeeitemPriceBo> cbfeeitems) {
        MMAInfo info = new MMAInfo();
        if (CollUtil.isNotEmpty(cbfeeitems)) {
            OptionalDouble average = cbfeeitems.stream().map(EcoCbfeeitem::getTargetnotaxprice).filter(targetnotaxprice -> !NumberUtil.isEmpty(targetnotaxprice)).mapToDouble(BigDecimal::doubleValue).average();
            Optional<BigDecimal> max = cbfeeitems.stream().map(EcoCbfeeitem::getTargetnotaxprice).filter(targetnotaxprice -> !NumberUtil.isEmpty(targetnotaxprice)).max(BigDecimal::compareTo);
            Optional<BigDecimal> min = cbfeeitems.stream().map(EcoCbfeeitem::getTargetnotaxprice).filter(targetnotaxprice -> !NumberUtil.isEmpty(targetnotaxprice)).min(BigDecimal::compareTo);
            info.setAvgPrice(NumberUtil.getValue(average.orElse(0)));
            info.setMaxPrice(max.orElse(BigDecimal.ZERO));
            info.setMinPrice(min.orElse(BigDecimal.ZERO));
        }
        return info;
    }

}
